import asyncio
from typing import Dict, Optional, Any
import logging
from datetime import datetime

from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.interval import IntervalTrigger
from apscheduler.triggers.cron import CronTrigger

# 设置APScheduler日志级别为WARNING，减少冗余日志
logging.getLogger('apscheduler').setLevel(logging.WARNING)

from .constant import QUEUE_CLEANUP_FREQUENCY
from .entities import (
    SecurityLevel, 
    CodeExecutionRequest, 
    ExecutionResult,
    ExecutorConfig
)
from .queue_manager import QueueManager
from .executor.base import BaseExecutor
from .executor.container_executor import ContainerExecutor
from .executor.secure_exec_executor import SecureExecExecutor

logger = logging.getLogger(__name__)

class ExecutorManager:
    """执行器管理器"""
    
    def __init__(self, k8s_config: Optional[Dict[str, Any]] = None):
        self.queue_manager = QueueManager()
        self.scheduler = AsyncIOScheduler()
        
        # 执行器实例
        self.executors: Dict[SecurityLevel, BaseExecutor] = {}
        
        # 默认配置
        self.default_configs = {
            SecurityLevel.LOW: ExecutorConfig(
                max_concurrent_tasks=10,
                default_timeout=30,
                resource_limits={"memory": "512Mi", "cpu": "1"}
            ),
            SecurityLevel.HIGH: ExecutorConfig(
                max_concurrent_tasks=3,
                default_timeout=120,
                resource_limits={"memory": "128Mi", "cpu": "0.25"}
            )
        }
        
        # 执行器映射策略
        self.executor_mapping = {
            SecurityLevel.LOW: "exec",      # 低安全等级使用安全exec执行器
            SecurityLevel.HIGH: "container"      # 高安全等级使用安全container执行器
        }
        
        self.k8s_config = k8s_config
        self._is_running = False
        
        # 初始化执行器
        self._initialize_executors()
        
        # 注册任务处理器
        self._register_task_processors()
    
    def _initialize_executors(self):
        """初始化执行器实例"""
        for security_level in SecurityLevel:
            executor_type = self.executor_mapping[security_level]
            config = self.default_configs[security_level]
            
            if executor_type == "exec":
                self.executors[security_level] = SecureExecExecutor(config)
                logger.info(f"初始化 {security_level.value} 级别的 SecureExecExecutor")
            elif executor_type == "container":
                if self.k8s_config:
                    self.executors[security_level] = ContainerExecutor(config, self.k8s_config)
                    logger.info(f"初始化 {security_level.value} 级别的 ContainerExecutor")
                else:
                    # 如果没有k8s配置，降级使用安全exec执行器
                    self.executors[security_level] = SecureExecExecutor(config)
                    logger.warning(f"没有k8s配置，{security_level.value} 级别降级使用 SecureExecExecutor")
    
    def _register_task_processors(self):
        """注册任务处理器到队列管理器"""
        for security_level, executor in self.executors.items():
            # 使用默认参数绑定executor实例，避免闭包变量捕获问题
            async def processor(request: CodeExecutionRequest, exec_instance=executor) -> ExecutionResult:
                return await exec_instance.run_task(request)
            
            self.queue_manager.register_task_processor(security_level, processor)
    
    async def submit_task(self, request: CodeExecutionRequest, priority: int = 0) -> str:
        """提交任务到队列"""
        task_id = await self.queue_manager.submit_task(request, priority)
        
        # 提交任务后立即触发对应安全等级的任务处理
        if self._is_running:
            try:
                await self._process_tasks_job(request.security_level)
            except Exception as e:
                logger.warning(f"立即处理任务失败，将由定时器处理: {e}")
        
        return task_id
    
    async def get_task_status(self, task_id: str) -> Optional[str]:
        """获取任务状态"""
        status = await self.queue_manager.get_task_status(task_id)
        return status.value if status else None
    
    async def get_task_result(self, task_id: str) -> Optional[ExecutionResult]:
        """获取任务结果"""
        return await self.queue_manager.get_task_result(task_id)
    
    async def cancel_task(self, task_id: str) -> bool:
        """取消任务"""
        return await self.queue_manager.cancel_task(task_id)
    
    def get_queue_info(self) -> Dict[str, Any]:
        """获取队列信息"""
        return self.queue_manager.get_all_queue_info()
    
    def get_executor_status(self) -> Dict[str, Any]:
        """获取执行器状态"""
        status = {}
        for security_level, executor in self.executors.items():
            status[security_level.value] = executor.get_status()
        return status
    
    def get_system_status(self) -> Dict[str, Any]:
        """获取系统整体状态"""
        return {
            "queue_info": self.get_queue_info(),
            "executor_status": self.get_executor_status(),
            "scheduler_running": self.scheduler.running,
            "manager_running": self._is_running,
            "uptime": datetime.utcnow().isoformat()
        }
    
    async def start(self):
        """启动执行器管理器"""
        if self._is_running:
            logger.warning("执行器管理器已经在运行")
            return
        
        logger.info("启动执行器管理器...")
        
        # 启动调度器
        self.scheduler.start()
        logger.info("APScheduler 已启动")
        
        # 为每个安全等级添加任务处理作业
        for security_level in SecurityLevel:
            # 使用更长的调度间隔，减少空轮询
            interval_seconds = {
                SecurityLevel.LOW: 5,      # 5秒间隔
                SecurityLevel.HIGH: 15      # 15秒间隔
            }
            
            job_id = f"process_{security_level.value}_tasks"
            
            self.scheduler.add_job(
                func=self._process_tasks_job,
                trigger=IntervalTrigger(seconds=interval_seconds[security_level]),
                args=[security_level],
                id=job_id,
                name=f"处理 {security_level.value} 安全等级任务",
                max_instances=1,  # 防止重复执行
                coalesce=True    # 合并错过的执行
            )
            
            logger.info(f"已添加 {security_level.value} 级别任务处理作业，间隔: {interval_seconds[security_level]}秒")
        
        # 添加清理作业
        self.scheduler.add_job(
            func=self._cleanup_job,
            trigger=CronTrigger(minute=QUEUE_CLEANUP_FREQUENCY), 
            id="cleanup_job",
            name="队列清理作业",
            max_instances=1
        )
        logger.info("已添加队列清理作业")
        
        self._is_running = True
        logger.info("执行器管理器启动完成")
    
    async def stop(self):
        """停止执行器管理器"""
        if not self._is_running:
            logger.warning("执行器管理器已经停止")
            return
        
        logger.info("停止执行器管理器...")
        
        # 停止调度器
        self.scheduler.shutdown(wait=True)
        logger.info("APScheduler 已停止")
        
        # 清理执行器
        for security_level, executor in self.executors.items():
            # 等待活跃任务完成
            while executor.get_active_task_count() > 0:
                logger.info(f"等待 {security_level.value} 执行器的 {executor.get_active_task_count()} 个任务完成...")
                await asyncio.sleep(1)
        
        self._is_running = False
        logger.info("执行器管理器已停止")
    
    async def _process_tasks_job(self, security_level: SecurityLevel):
        """处理指定安全等级的任务作业"""
        try:
            # 先检查队列是否有任务，避免无意义的轮询
            queue_info = self.queue_manager.get_queue_info(security_level)
            if queue_info["is_empty"]:
                return
            
            executor = self.executors[security_level]
            
            # 检查执行器是否可以接受新任务
            if not executor.can_accept_task():
                return
            
            # 从队列获取任务
            task = await self.queue_manager.get_task(security_level)
            if not task:
                return
            
            try:
                # 提交任务到执行器，传递队列的task_id
                result = await executor.run_task(task.payload, task.task_id)
                
                # 更新任务状态
                await self.queue_manager.complete_task(
                    task.task_id, 
                    result, 
                    result.status
                )
                
                logger.debug(f"任务 {task.task_id} 处理完成，状态: {result.status}")
                
            except Exception as e:
                logger.error(f"处理任务 {task.task_id} 失败: {e}")
                
                # 创建失败结果对象
                from entities import TaskStatus, ExecutionResult
                from datetime import datetime
                
                failed_result = ExecutionResult(
                    task_id=task.task_id,
                    status=TaskStatus.FAILED,
                    error=f"执行器处理失败: {str(e)}",
                    output=None,
                    return_code=-1,
                    execution_time=0.0,
                    memory_usage=0,
                    cpu_usage=0.0,
                    start_time=datetime.utcnow(),
                    end_time=datetime.utcnow()
                )
                
                # 标记任务失败
                await self.queue_manager.complete_task(
                    task.task_id,
                    failed_result,
                    TaskStatus.FAILED
                )
                
        except Exception as e:
            logger.error(f"处理 {security_level.value} 任务作业失败: {e}")
    
    async def _cleanup_job(self):
        """系统清理作业"""
        try:
            logger.debug("执行系统清理作业")
            
            # 清理过期的任务结果（保留1小时）
            current_time = datetime.utcnow()
            expired_tasks = []
            
            for task_id, result in self.queue_manager.task_results.items():
                if hasattr(result, 'end_time') and result.end_time:
                    age = (current_time - result.end_time).total_seconds()
                    if age > 3600:  # 1小时
                        expired_tasks.append(task_id)
            
            # 移除过期任务
            for task_id in expired_tasks:
                if task_id in self.queue_manager.task_results:
                    del self.queue_manager.task_results[task_id]
                if task_id in self.queue_manager.task_status:
                    del self.queue_manager.task_status[task_id]
            
            if expired_tasks:
                logger.info(f"清理了 {len(expired_tasks)} 个过期任务结果")
            
            # 清理执行器中的已完成任务
            for executor in self.executors.values():
                initial_count = len(executor.task_results)
                
                # 清理1小时前的任务结果
                expired_executor_tasks = []
                for task_id, result in executor.task_results.items():
                    if hasattr(result, 'end_time') and result.end_time:
                        age = (current_time - result.end_time).total_seconds()
                        if age > 3600:
                            expired_executor_tasks.append(task_id)
                
                for task_id in expired_executor_tasks:
                    if task_id in executor.task_results:
                        del executor.task_results[task_id]
                
                cleaned_count = len(expired_executor_tasks)
                if cleaned_count > 0:
                    logger.debug(f"执行器清理了 {cleaned_count} 个过期任务结果")
            
        except Exception as e:
            logger.error(f"系统清理作业失败: {e}")
    
    def configure_executor(self, security_level: SecurityLevel, config: ExecutorConfig):
        """配置执行器"""
        if security_level in self.executors:
            # 重新创建执行器实例
            executor_type = self.executor_mapping[security_level]
            
            if executor_type == "exec":
                self.executors[security_level] = SecureExecExecutor(config)
            elif executor_type == "container" and self.k8s_config:
                self.executors[security_level] = ContainerExecutor(config, self.k8s_config)
            
            logger.info(f"已重新配置 {security_level.value} 级别执行器")
    
    def update_executor_mapping(self, mapping: Dict[SecurityLevel, str]):
        """更新执行器映射策略"""
        self.executor_mapping.update(mapping)
        # 重新初始化执行器
        self._initialize_executors()
        # 重新注册任务处理器
        self._register_task_processors()
        logger.info("执行器映射策略已更新") 